package org.parademo.reasoning;

import jess.*;
import org.parademo.database.DataStorageImpl;
import org.parademo.jess.SimpleRuleConflictResolutionStrategy;
import org.parademo.model.ProposalEntity;
import org.parademo.model.ProposalStatus;

/**
 * @author Ajit Skanda
 * @version 1.0
 */
public class ReasoningEngine {

	private Rete rulesEngine;
    private WorkingMemoryMarker marker;
    private DataStorageImpl dataStorage;

    public ReasoningEngine(DataStorageImpl pDataStorage) throws JessException {

        // Create a Jess rule rulesEngine
        rulesEngine = new Rete();
        rulesEngine.reset();
	    
	    //set the strategy for choosing rules
	    rulesEngine.setStrategy(new SimpleRuleConflictResolutionStrategy());

        // Load the reasoning rules
        rulesEngine.batch("Parademo_reasoning_engine/impl1.clp");

        // Load the catalog data into working memory
        dataStorage = pDataStorage;
        rulesEngine.addAll(dataStorage.getAllCommunities().values());
        rulesEngine.addAll(dataStorage.getAllUsers().values());

        // Mark end of Community and User data storage for later
        marker = rulesEngine.mark();
    }

	public void processProposal(ProposalEntity proposal) throws JessException {
		// Remove any previous proposals, leaving only the communities and user data
		rulesEngine.resetToMark(marker);

		// Load data for this proposal
		loadProposalData(proposal);

		// Fire the rules that apply to this proposal(if any)
		rulesEngine.run();

		//Check and Return the list of results created by the rules
	}

	private void loadProposalData(ProposalEntity proposal) throws JessException {

		//How to create a shadow fact and assert it through code?? Is this why the rules are not getting triggered?
		
		//proposalTemplate.
		Deftemplate proposalTemplate = new Deftemplate("Proposal", "To represent a user proposal", rulesEngine);
		/*proposalTemplate.addSlot("title", new Value(proposal.getTitle(), RU.STRING),"STRING");
		proposalTemplate.addSlot("description", new Value(proposal.getDescription(), RU.STRING),"STRING");
		proposalTemplate.addSlot("internal", new Value(proposal.isInternal()),"STRING");
		proposalTemplate.addSlot("votingStartDate", new Value(proposal.getVotingStartDate()),"STRING");
		proposalTemplate.addSlot("votingEndDate", new Value(proposal.getVotingEndDate()),"STRING");
		proposalTemplate.addSlot("author", new Value(proposal.getAuthor()),"OBJECT");
		proposalTemplate.addSlot("category", new Value(proposal.getCategory()),"INTEGER");
		proposalTemplate.addSlot("status", new Value(proposal.getStatus()),"INTEGER");

		ValueVector votesVector = new ValueVector(proposal.getVotes().size());
		votesVector.addAll(proposal.getVotes());
		proposalTemplate.addSlot("votes", new Value(votesVector, RU.LIST),"STRING");
		rulesEngine.addDeftemplate(proposalTemplate);*/

		//Create a Fact for the proposal in the working memory
		//Fact proposalFact = new Fact(proposalTemplate);
		Fact proposalFact = new Fact("Proposal", rulesEngine);
		rulesEngine.assertFact(proposalFact);                       //assert it to invoke rule(s)
		
		//rulesEngine.add(proposal);

		//Change status for the newly accepted proposal.
		proposal.setStatus(ProposalStatus.VOTABLE);
		dataStorage.createProposal(proposal);
	}

	public void run(ProposalEntity proposal) throws JessException {
        // Remove any previous proposals, leaving only the communities and user data
    	rulesEngine.resetToMark(marker);

    	// Load data for this proposal
        loadProposalData(proposal);
		//rulesEngine.

        // Fire the rules that apply to this proposal(if any)
        rulesEngine.run();

        //Check and Return the list of results created by the rules
    }

	public void deleteRule(String ruleName, String assertStatement) throws JessException {
		// Remove any previous proposals, leaving only the communities and user data
    	rulesEngine.resetToMark(marker);

		//count the number of rules
		
		//rulesEngine.assertString(assertStatement);
		Defglobal deleteGlobalVariable = rulesEngine.findDefglobal("*trigger-rule-change*");
		//System.out.println("deleteGlobalVariable.toString() = " + deleteGlobalVariable.toString());
		//remove the defglobal and re-define it to set its value to TRUE?

		rulesEngine.run();
		//rulesEngine.removeDefrule(ruleName);

		//count the no. of rules again to show that a rule has been deleted.
	}
}
